package bold.storage.component;

import bold.storage.core.DB;
import bold.storage.core.Record;
import bold.storage.splice.SqlKit;
import bold.storage.util.FilterUtil;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class Model {
    private String table;
    private Record record;
    private List<Map<String, Object>> mapList;

    Model(String table) {
        this.table = table;
        this.record = new Record();
    }

    Model(String table, Map<String, String> map) {
        this.table = table;
        this.record = new Record();
        this.record.putAll(map);
    }

    Model(String table, List<Map<String, Object>> mapList) {
        this.table = table;
        this.mapList = mapList;
    }

    public Model set(String col, Object value) {
        this.record.put(col, value);
        return this;
    }

    public Model setNull(String col) {
        this.record.put(col, null);
        return this;
    }

    public Model setPk(Object pk) {
        this.record.put(SqlKit.getPk(), pk);
        return this;
    }

    public String getPk() {
        return (String) this.record.get(SqlKit.getPk());
    }

    String table() {
        return this.table;
    }

    public Model table(String table) {
        this.table = table;
        return this;
    }

    public Model filter() {
        record = FilterUtil.filter(record, table);
        return this;
    }

    public boolean insert() throws SQLException {
        return (this.record != null && this.record.size() > 0)
                &&
                DB.insert(SqlKit.generateInsertSql(this.table(), this.record), this.record.values().toArray()) > 0;
    }

    public boolean insertBatch() throws SQLException {
        if (this.mapList != null && this.mapList.size() > 0) {
            int[] resultCount = DB.insertBatch(SqlKit.generateInsertSql(this.table(), this.mapList.get(0)), this.mapList);
            for (int i : resultCount) {
                if (i <= 0) return false;
            }
            return true;
        } else {
            return false;
        }
    }

    public boolean update(Where where) throws SQLException {
        String sql = SqlKit.generateUpdateSql(this.table(), this.record, where.sql());
        Object[] params = SqlKit.join(this.record.values(), where.param());
        return DB.update(sql, params) > 0;
    }

    public boolean updateBy(String col, String value) throws SQLException {
        return this.update(new Where(col, value));
    }

    public boolean updateByPk(String value) throws SQLException {
        return this.updateBy(SqlKit.getPk(), value);
    }

    public boolean updateByPk() throws SQLException {
        return this.updateByPk(this.getPk());
    }

    public boolean replace() throws SQLException {
        return DB.update(SqlKit.generateReplaceSql(this.table(), this.record), this.record.values().toArray()) > 0;
    }

    public boolean delete(Where where) throws SQLException {
        return DB.update(SqlKit.generateDeleteSql(this.table(), where.sql()), where.param().toArray()) > 0;
    }

    public boolean deleteBy(String col, String value) throws SQLException {
        return this.delete(new Where(col, value));
    }

    public boolean deleteByPk(String pk) throws SQLException {
        return this.deleteBy(SqlKit.getPk(), pk);
    }

    public boolean deleteByPk() throws SQLException {
        return this.deleteBy(SqlKit.getPk(), this.getPk());
    }

    public boolean increase(String col) throws SQLException {
        return this.increase(col, "1");
    }

    public boolean increase(String col, String num) throws SQLException {
        Where where = new Where(SqlKit.getPk(), this.getPk());
        return this.increase(col, num, where);
    }

    public boolean increase(String col, Object num, Where where) throws SQLException {
        return DB.update(SqlKit.generateIncreaseSql(true, this.table(), col, where.sql()), SqlKit.join(num, where.param())) > 0;
    }

    public boolean decrease(String col) throws SQLException {
        return this.decrease(col, Integer.valueOf(1));
    }

    public boolean decrease(String col, Object num) throws SQLException {
        Where where = new Where(SqlKit.getPk(), this.getPk());
        return this.decrease(col, num, where);
    }

    public boolean decrease(String col, Object num, Where where) throws SQLException {
        return DB.update(SqlKit.generateIncreaseSql(false, this.table(), col, where.sql()), SqlKit.join(num, where.param())) > 0;
    }

}
